﻿// @brief
// @file Device.cs
// @date 2024年08月07日
// @author doublecat
// 
// Copyright (C) &lt;2024&gt;  &lt;doublecat&gt;
// 
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

using System.Xml.Serialization;

namespace doublecat.mcu.svd;

[XmlRoot("device")]
public class Device : IRegisterGroup {
    private uint? _size;

    [XmlElement("addressUnitBits")]
    public uint AddressUnitBits { get; set; }

    [XmlElement("cpu")]
    public Cpu? Cpu { get; set; }

    [XmlElement("description")]
    public string? Description { get; set; }

    [XmlElement("headerDefinitionsPrefix")]
    public string? HeaderDefinitionsPrefix { get; set; }

    [XmlElement("headerSystemFilename")]
    public string? HeaderSystemFilename { get; set; }

    [XmlElement("lienseText")]
    public string? LicenseText { get; set; }

    [XmlElement("name", IsNullable = false)]
    public required string Name { get; set; }

    [XmlArray("peripherals")]
    [XmlArrayItem("peripheral")]
    public List<Peripheral> Peripherals { get; set; } = [];

    [XmlElement("series")]
    public string? Series { get; set; }

    [XmlElement("vendor")]
    public string? Vendor { get; set; }

    [XmlElement("vendorExtensions")]
    public object? VendorExtensions { get; set; }

    public string? VendorId { get; set; }

    [XmlElement("version")]
    public string? Version { get; set; }

    [XmlElement("width")]
    public uint Width { get; set; }

    #region IRegisterGroup Members

    [XmlElement("size")]
    public string? Size {
        get => _size?.ToString();
        set => _size = value?.ToUInt();
    }

    [XmlElement("access")]
    public string? Access { get; set; }

    [XmlElement("protection")]
    public string? Protection { get; set; }

    [XmlElement("resetValue")]
    public string? ResetValue { get; set; }

    [XmlElement("resetMask")]
    public string? ResetMask { get; set; }

    #endregion

    public Peripheral? FindPeripheral(string name) {
        return Peripherals.Find(p => p.Name == name);
    }

    public uint GetSize() {
        if (_size is null)
            throw new Exception("Device attribute 'size' not set!");
        return _size.Value;
    }
}
